package api

import (
	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/infraboard/mcube/v2/http/gin/response"
	"github.com/infraboard/mcube/v2/ioc"
	"gitlab.com/go-course-project/go17/vblog/apps/blog"
	"gitlab.com/go-course-project/go17/vblog/middleware"

	// 引入Gin Root Router: *gin.Engine
	ioc_gin "github.com/infraboard/mcube/v2/ioc/config/gin"
)

// 上传怎么用:
// main.go 组装的时候，传入具体实现, 实现了业务的 插件化
// 访问我们mock测试, 有助于构造 小规模的单元环境
// func NewBlogApiHandler(blogImpl blog.Service) *BlogApiHandler {
// 	return &BlogApiHandler{
// 		blog: blogImpl,
// 	}
// }

func init() {
	ioc.Api().Registry(&BlogApiHandler{})
}

type BlogApiHandler struct {
	ioc.ObjectImpl
	blog blog.Service
}

// module_name
func (h *BlogApiHandler) Name() string {
	return "blogs"
}

// router := r.Group("/vblog/api/v1/blogs")
// ioc_gin.ObjectRouter(h)
// 模块的名称, 会作为路径的一部分比如: /api/mcube_service/v1/hello_module/
// /api/xxx_service
// 路径构成规则 /<path_prefix>/<service_name>/<service_version>/<module_name>
func (h *BlogApiHandler) Init() error {
	h.blog = blog.GetService()
	// 在ioc获取gin server *gin.Engine
	ioc_gin.RootRouter()

	// 获取模块路有: url前缀,
	r := ioc_gin.ObjectRouter(h)
	r.GET("", h.QueryBlog)
	r.GET(":id", h.DescribeBlog)

	r.Use(middleware.Auth)
	r.POST("", h.CreateBlog)
	r.PUT(":id", h.UpdateBlog)
	r.DELETE(":id", h.DeleteBlog)
	r.POST(":id/publish", h.PublishBlog)
	return nil
}

// BODY
func (h *BlogApiHandler) CreateBlog(ctx *gin.Context) {
	in := &blog.CreateBlogRequest{}
	if err := ctx.BindJSON(in); err != nil {
		response.Failed(ctx, err)
		return
	}
	ins, err := h.blog.CreateBlog(ctx.Request.Context(), in)
	if err != nil {
		response.Failed(ctx, err)
		return

	}
	response.Success(ctx, ins)
}

func (h *BlogApiHandler) QueryBlog(ctx *gin.Context) {
	in := blog.NewQueryBlogRequest()
	// GET /search?name=John&age=30&country=USA
	// type SearchQuery struct {
	// 	Name   string `form:"name"`
	// 	Age    int    `form:"age"`
	// 	Country string `form:"country"`
	// }
	if err := ctx.BindQuery(in); err != nil {
		response.Failed(ctx, err)
		return
	}
	in.SetTag(ctx.Query("tag"))

	ins, err := h.blog.QueryBlog(ctx.Request.Context(), in)
	if err != nil {
		response.Failed(ctx, err)
		return
	}
	response.Success(ctx, ins)
}

func (h *BlogApiHandler) PublishBlog(ctx *gin.Context) {
	idInt, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		response.Failed(ctx, err)
		return
	}

	req := blog.NewPublishBlogRequest(uint(idInt))
	if err := ctx.BindJSON(req); err != nil {
		response.Failed(ctx, err)
		return
	}

	ins, err := h.blog.PublishBlog(ctx.Request.Context(), req)
	if err != nil {
		response.Failed(ctx, err)
		return
	}
	response.Success(ctx, ins)
}

func (h *BlogApiHandler) DescribeBlog(ctx *gin.Context) {
	idInt, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		response.Failed(ctx, err)
		return
	}

	req := blog.NewDescribeBlogRequest(uint(idInt))
	ins, err := h.blog.DescribeBlog(ctx.Request.Context(), req)
	if err != nil {
		response.Failed(ctx, err)
		return
	}
	response.Success(ctx, ins)
}

func (h *BlogApiHandler) DeleteBlog(ctx *gin.Context) {
	in := blog.NewDeleteBlogRequest(ctx.Param("id"))

	err := h.blog.DeleteBlog(ctx.Request.Context(), in)
	if err != nil {
		response.Failed(ctx, err)
		return
	}
	response.Success(ctx, "ok")
}

func (h *BlogApiHandler) UpdateBlog(ctx *gin.Context) {
	idInt, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		response.Failed(ctx, err)
		return
	}

	in := blog.NewUpdateBlogRequest(uint(idInt))
	if err := ctx.BindJSON(in); err != nil {
		response.Failed(ctx, err)
		return
	}

	ins, err := h.blog.UpdateBlog(ctx.Request.Context(), in)
	if err != nil {
		response.Failed(ctx, err)
		return
	}
	response.Success(ctx, ins)
}
